/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package me.panpf.sketch.sample.widget;

import ohos.agp.components.AttrSet;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.utils.Rect;
import ohos.app.Context;

import java.util.*;

/**
 * DoubleFinsEmptyView
 */
public class DoubleFinsEmptyView extends DirectionalLayout {

    public DoubleFinsEmptyView(Context context) {
        this(context, null);
    }

    public DoubleFinsEmptyView(Context context, AttrSet attrSet) {
        this(context, attrSet, "");
    }

    public DoubleFinsEmptyView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(context);
    }

    private void init(Context context) {
        Rect boundsRect = new Rect(0, 0, 100, 100);

        ArrayList<Rect> fullRectList = new ArrayList<Rect>();

        fullRectList.add(new Rect(0, 0, 25, 25));
        fullRectList.add(new Rect(25, 0, 50, 25));
        fullRectList.add(new Rect(50, 0, 75, 25));
        fullRectList.add(new Rect(75, 0, 100, 25));

        fullRectList.add(new Rect(0, 25, 25, 50));
        fullRectList.add(new Rect(25, 25, 50, 50));
        fullRectList.add(new Rect(50, 25, 75, 50));
        fullRectList.add(new Rect(75, 25, 100, 50));

        fullRectList.add(new Rect(0, 50, 25, 75));
        fullRectList.add(new Rect(25, 50, 50, 75));
        fullRectList.add(new Rect(50, 50, 75, 75));
        fullRectList.add(new Rect(75, 50, 100, 75));

        fullRectList.add(new Rect(0, 75, 25, 100));
        fullRectList.add(new Rect(25, 75, 50, 100));
        fullRectList.add(new Rect(50, 75, 75, 100));
        fullRectList.add(new Rect(75, 75, 100, 100));

        setOrientation(VERTICAL);

        FindEmptyView originView = new FindEmptyView(context);
        originView.setBoundsRect(boundsRect);
        originView.setFullRectList(fullRectList);

        FindEmptyView findEmptyView = new FindEmptyView(context);
        findEmptyView.setBoundsRect(boundsRect);
        ArrayList<Rect> newFullRectList = new ArrayList<Rect>(fullRectList.size());
        for (Rect fullRect : fullRectList) {
            newFullRectList.add(fullRect);
        }
        List<Rect> emptyRectList = findEmptyRect(boundsRect, newFullRectList);
        findEmptyView.setFullRectList(newFullRectList);
        findEmptyView.setEmptyRectList(emptyRectList);

        addComponent(originView, new ComponentContainer.LayoutConfig(500, 500));
        addComponent(findEmptyView, new ComponentContainer.LayoutConfig(500, 500));
    }

    /**
     * findEmptyRect
     *
     * @param rect
     * @param childRectList
     * @return List<Rect>
     */
    public List<Rect> findEmptyRect(Rect rect, List<Rect> childRectList) {
        if (rect.isEmpty()) {
            return null;
        }
        List<Rect> emptyRectList = null;
        if (childRectList == null || childRectList.size() == 0) {
            return addSingleRect(rect);
        }
        // 按离左上角的距离排序
        childRectList = sortList(childRectList);
        int left = rect.left;
        int top = rect.top;
        int right = 0;
        int bottom = -1;
        Rect lastRect = null;
        Rect childRect;
        Iterator<Rect> rectIterator = childRectList.iterator();
        while (rectIterator.hasNext()) {
            childRect = rectIterator.next();
            boolean newLine = lastRect == null || (childRect.top >= bottom);
            if (newLine) {
                // 首先要处理上一行的最后一个
                if (lastRect != null) {
                    if (lastRect.right < rect.right) {
                        emptyRectList = addEmptyRect(emptyRectList, lastRect.right, top, rect.right, bottom);
                    }
                }
                // 然后要更新top和bottom
                top = bottom != -1 ? bottom : top;
                bottom = childRect.bottom;
                // 左边有空隙
                if (childRect.left > left) {
                    emptyRectList = addEmptyRect(emptyRectList, left, childRect.top, childRect.left, childRect.bottom);
                }
                // 顶部有空隙
                if (childRect.top > top) {
                    emptyRectList = addEmptyRect(emptyRectList, left, top, childRect.right, childRect.top);
                }
                right = childRect.right;
                lastRect = childRect;
            } else {
                boolean available = childRect.bottom == lastRect.bottom;
                if (available) {
                    // 左边有空隙
                    if (childRect.left > right) {
                        emptyRectList = addEmptyRect(emptyRectList, right, top, childRect.left, bottom);
                    }
                    // 顶部有空隙
                    if (childRect.top > top) {
                        emptyRectList = addEmptyRect(emptyRectList, childRect.left, top, childRect.right, childRect.top);
                    }
                    right = childRect.right;
                    lastRect = childRect;
                } else {
                    rectIterator.remove();
                }
            }
        }
        // 最后的结尾处理
        if (right < rect.right) {
            emptyRectList = addEmptyRect(emptyRectList, right, top, rect.right, bottom);
        }
        if (bottom < rect.bottom) {
            emptyRectList = addEmptyRect(emptyRectList, rect.left, bottom, rect.right, rect.bottom);
        }
        return emptyRectList;
    }

    private List<Rect> addSingleRect(Rect rect){
        List<Rect> emptyRectList = new LinkedList<Rect>();
        emptyRectList.add(rect);
        return emptyRectList;
    }

    private List<Rect> addEmptyRect(List<Rect> emptyRectList, int left, int top, int right, int bottom) {
        Rect leftEmptyRect = new Rect(left, top, right, bottom);
        if (emptyRectList == null) {
            emptyRectList = new LinkedList<Rect>();
        }
        emptyRectList.add(leftEmptyRect);
        return emptyRectList;
    }

    private List<Rect> sortList(List<Rect> childRectList) {
        List<Rect> temp = childRectList;
        Collections.sort(temp, new Comparator<Rect>() {
            @Override
            public int compare(Rect o1, Rect o2) {
                if (o1.top >= o2.bottom || o2.top >= o1.bottom) {
                    return o1.top - o2.top;
                } else {
                    return o1.left - o2.left;
                }
            }
        });
        return temp;
    }

}
